<?php
/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

define('IN_PHP', 'true');
define('iW2P_DEBUG', 'true');
//enable gz compression
ob_start('ob_gzhandler');

include('config.php');
include('inc/IXR_Library_INFLobbyPatch.inc.php');
include('inc/INFLobbyDB.inc.php');
include('inc/php-captcha_INFLobbyPatch.inc.php');


//register_shutdown_function(errorHandler);
//function errorHandler() {
	//print_r($_GLOBALS['server']);
//	$_GLOBALS['server']->error(0, 'testError');
//}

function genSessionId() {
	//return rand(0,1) ? 1000 : rand(1000,PHP_INT_MAX); //produces collisions for testing purposes
	
	return rand(1000,PHP_INT_MAX);
}

class INFLobby extends IXR_IntrospectionServer {
	function INFLobby() {	
		$this->IXR_IntrospectionServer();
		$this->addCallback(
            'INFLobby.getPollTimings',
            'this:getPollTimings',
            array('struct'),
            '
Returns the servers required poll intervalls during "waiting" and "playing" state (they are different).
@return struct(
    int waiting => required poll intervall during waiting state,
    int playing => required poll intervall during playing state
)'
        );
        
        $this->addCallback(
			'INFLobby.getChallenge',
			'this:getChallenge',
			array('struct'),
			'
Returns a challenge (captcha) for the client to login.
@return struct(
    int challengeid => the id of the challenge
    string mimetype => what kind of challenge is this (currently only image/jpeg)
    base64 content => the challenge file content
)'
        );

		$this->addCallback(
			'INFLobby.getSessionId',
			'this:getSessionId',
			array('int', 'int', 'string'),
			''
		);
		$this->addCallback(
			'INFLobby.setNickname',
			'this:setNickname',
			array('boolean', 'int', 'string'),
			''
		);
		
		$this->addCallback(
			'INFLobby.getQueues',
			'this:getQueues',
			array('array', 'int'),
			''
		);
		
		$this->addCallback(
			'INFLobby.setQueues',
			'this:setQueues',
			array('boolean', 'int', 'array'),
			''
		);
		
		$this->addCallback(
			'INFLobby.setStatus',
			'this:setStatus',
			array('boolean', 'int', 'int'),
			''
		);
		
		$this->addCallback(
			'INFLobby.pollUpdates',
			'this:pollUpdates',
			array('struct', 'int'),
			''
		);
		
		$this->addCallback(
			'INFLobby.pollKeepAlive',
			'this:pollKeepAlive',
			array('boolean', 'int'),
			''
		);
		
		$this->serve();
	}
	function getPollTimings($args) {
		global $config;
		//input sanitizing
		//no args
		
		return array('waiting' => $config['serverconfig']['sessionLifeTime'], 'playing' => $config['serverconfig']['sessionLifeTime']*10);
	}
	
	function getChallenge($args) {
		//input sanitizing
		//no args
		
		//connect to DB and clean out old, invalid challenges
		$db = new INFLobbyDB();
		$db->cleanupChallenges();
		
		//create a CAPTCHA
		$aFonts = array('inc/fonts/bitstream/VeraBd.ttf', 'inc/fonts/bitstream/VeraIt.ttf', 'inc/fonts/bitstream/Vera.ttf');
		//$aFonts = array('inc/fonts/isabella/Isabella.ttf');
		
		$oVisualCaptcha = new PhpCaptcha($aFonts, 200, 60);
		//write it to the disk
		$oVisualCaptcha->Create('tmp/captcha.jpeg');
		//read file into string
		$data = file_get_contents('tmp/captcha.jpeg');
		//base64 encode content
		$challenge = new IXR_Base64($data);
		
		//create a challengeid and save the challenge text
		$challengeId = $db->saveChallenge($oVisualCaptcha->sCode, $_SERVER['REMOTE_ADDR'], time());
		
		return array('challengeid' => $challengeId, 'mimetype' => 'image/jpeg', 'content' => $challenge);
		
	}

	function getSessionId($args) {
		//input sanitizing
		$challengeId = intval($args[0]);
		$matches = preg_match('/[0-9a-zA-Z]*/', $args[1]);
		$challengeReply = $matches[0];
		
		//connect to DB
		$db = new INFLobbyDB();
		//retrieve challenge data for challengeId
		$challengeData = $db->getChallenge($challengeId);
		
		if(!$challengeData)return 0;
		else {
			
			//check if ip and reply are correct
			if(defined(iW2P_DEBUG) ||
				(strcmp($_SERVER['REMOTE_ADDR'], $challengeData['ip'])== 0 &&
				strcmp($challengeReply, $challengeData['reply'])==0))
			{
				//delete challenge
				$db->deleteChallenge($challengeId);
				
				//cleanup sessions
				$db->cleanupSessions();
				
				//create a sessionid and save it
				$sessionId = $db->saveSession('genSessionId');
				
				return $sessionId;				
			}
		}
		
		return 0;
	}
		
	function setNickname($args) {
		//input sanitizing
		$sessionId = intval($args[0]);
		$nickname = strval($args[1]); //nicknames can be anything - beware
		
		$db = new INFLobbyDB();
		return $db->setNickname($sessionId, $nickname);
	}
	
	function getQueues($args) {
		global $config;
		//input sanitizing
		$sessionId = intval($args);
		
		$db = new INFLobbyDB();
		$userid = $db->getUserId($sessionId);
		
		if($userid) {
			$queueinfo = $db->getQueueInfo();
			
			foreach($config['queues'] as $i => $v) {
				$v['queueid'] = $i+1;
				$v['count'] = count($queueinfo[$i+1]);
				$reply[] = $v;
			}
			return $reply;
		} else {
			return array();
		}
	}
    
	function setQueues($args) {
		//input sanitizing
		$sessionId = intval($args[0]);
		if(!is_array($args[1]))return false;
		foreach($args[1] as $v)$queueIds[] = intval($v);
		
		$db = new INFLobbyDB();
		
		$userid = $db->getUserId($sessionId);
		if($userid) {
			return $db->setQueueInfo($userid, $queueIds);
		} else {
			return false;
		}
	}
	
	function setStatus($args) {
		//input sanitizing
		$sessionId = intval($args[0]);
		$status = intval($args[1]); //playing = queueid / waiting = 0 / logout = -1
		
		if($status>=0) {
			$db = new INFLobbyDB();
			$success = $db->setStatus($sessionId, $status);
			if($status>0) {
				$userid = $db->getUserId($sessionId);
				if($userid)$success = $success && $db->setQueueInfo($userid, array());
				else $success=false;
			}
			
			return $success;
		} else {
			//logout via autoclean
			return true;
		}
	}
    
	function pollUpdates($args) {
		//input sanitizing
		$sessionId = intval($args);
		
		$db = new INFLobbyDB();
		
		//cleanup sessions
		$db->cleanupSessions();
		
		//check if user is alive
		$userid = $db->getUserId($sessionId);
		if($userid) {
			//give him some more livetime ;)
			$db->updateLastpoll($userid);
			
			$queueinfo = $db->getQueueInfo();
			$userinfo = $db->getUserInfo();
			
			$out = array();
			if(!empty($queueinfo))$out['queues'] = $queueinfo;
			$out['users'] = $userinfo;
			
			return $out;
		} else {
			return false;
		}
	}
	
	function pollKeepAlive($args) {
		//input sanitizing
		$sessionId = intval($args);
		
		$db = new INFLobbyDB();
	
		//cleanup sessions
		$db->cleanupSessions();
		
		//check if user is alive
		$userid = $db->getUserId($sessionId);
		if($userid) {
			//give him some more livetime
			$db->updateLastpoll($userid);
			
			return true;
		} else {
			return false;
		}
	}

}

$server = new INFLobby();

?>